package br.edu.ufcg.lp2;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;
import java.util.TreeSet;


/**
 * This class represents a name choice process.
 * 
 * @author João Pedro Leôncio <joopeeds@gmail.com>
 * @author Franco Stefano <stefano.tejo@gmail.com>
 * @author Fellype Cavalcante <fellype.cavalcante@gmail.com>
 */


public class Game implements Serializable{

	private static final long serialVersionUID = 1L;
	private ArrayList<User> users;
	private String id;
	private TreeSet<Name> namesVoted;
	

	/**
	 * 
	 * @param id
	 * 		The id
	 */
	
	
	public Game(String id) throws Exception{
		setId(id);
		users = new ArrayList<User>();
		namesVoted = new TreeSet<Name>(new RatingComparator());
	}

	

	public ArrayList<User> getUsers() {
		return users;
	}



	/**
	 * Changes the id 
	 * @param  id
	 * 		The id itself
	 * @throws Exception
	 * 		If the id is an empty string
	 */

	private void setId(String id) throws Exception {
		if(id.trim().length()==0) throw new Exception("Id cannot be empty");
		this.id = id;
	}
	
	
	/**
	 * Gets the id itself
	 * @return
	 * 		The id
	 */
	 
	public String getId() {
		return id;
	}

	/**
	 * Adds a user
	 * @param  user
	 * 		The user itself
	 */


	public void addUser(User user){
		users.add(user);
	}
	
	/**
	 * Removes a user
	 * @param  user
	 * 		The user itself
	 */
	
	
	public void removeUser(User user){
		users.remove(user);
	}
	
	/**
	 * Returns a treeSet of names sorted by theirs ratings
	 */
	
	
	public TreeSet<Name> getNamesByRating(){
		return namesVoted;
	}
	

	/**
	 * Adds ratings to a name, and that name comes to calculating your grade. When you like a name, it means you love him.
	 * @param name
	 * 		The name itself
	 * @param user
	 * 		The user itself
	 */		
	
	
	public void like(Name name, User user) throws Exception{
		if(!users.contains(user)) throw new Exception("User has not joined this game");
		if(!namesVoted.contains(name)) namesVoted.add(name.clone());
		for(Name nameVoted: namesVoted)
			if(nameVoted.equals(name))
				nameVoted.addVote(new Vote(Vote.LIKE, user));
	}
	

	/**
	 * Adds ratings to a name, and that name comes to calculating your grade. When you Halflike a name, it means you liked a little him.
	 * @param name
	 * 		The name itself
	 * @param user
	 * 		The user itself
	 */		
	
	
	public void dislike(Name name, User user) throws Exception{
		if(!users.contains(user)) throw new Exception("User has not joined this game");
		if(!namesVoted.contains(name)) namesVoted.add(name.clone());
		for(Name nameVoted: namesVoted)
			if(nameVoted.equals(name))
				nameVoted.addVote(new Vote(Vote.DISLIKE, user));
	}
	

	/**
	 * Adds ratings to a name, and that name comes to calculating your grade. When you Dislike a name, it means you hate him.
	 * @param name
	 * 		The name itself
	 * @param user
	 * 		The user itself
	 */		
	
	public void halflike(Name name, User user) throws Exception{
		if(!users.contains(user)) throw new Exception("User has not joined this game");
		if(!namesVoted.contains(name)) namesVoted.add(name.clone());
		for(Name nameVoted: namesVoted)
			if(nameVoted.equals(name))
				nameVoted.addVote(new Vote(Vote.HALFLIKE, user));
	}
	
}